package org.jsrml.common.unitofwork.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.jsrml.common.persistence.BaseCommand;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 切点类
 */
@Aspect
@Component
public class UnitOfWorkAspect {

	// Service层切点
	@Pointcut("@annotation(org.jsrml.common.unitofwork.aop.UseUnitOfWork)")
	public void serviceAspect() {
	}

	@Before("serviceAspect()")
	public void doBefore(JoinPoint joinPoint) {
		Object[] arguments = joinPoint.getArgs();
		if (arguments != null && arguments.length > 0) {
			BaseCommand command = (BaseCommand) arguments[0];

			/**
			 * 填充当前登录人信息
			 */
		}
	}

	@After("serviceAspect()")
	public void doAfter(JoinPoint joinPoint) {
		Object[] arguments = joinPoint.getArgs();
		if (arguments != null && arguments.length > 0) {
			BaseCommand command = (BaseCommand) arguments[0];

			command.getUnitOfWork().publish(true);
		}
	}

	/**
	 * 用于拦截service层记录业务事件日志
	 * 
	 * @param joinPoint
	 * @param e
	 */
	@AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
	public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {

		Object[] arguments = joinPoint.getArgs();
		if (arguments != null && arguments.length > 0) {
			BaseCommand command = (BaseCommand) arguments[0];

			command.getUnitOfWork().publish(true);
		}
	}

	/**
	 * 获取注解中对方法的描述信息 用于service层注解
	 * 
	 * @param joinPoint
	 *            切点
	 * @return 方法描述
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static String getServiceMthodDescription(JoinPoint joinPoint) throws Exception {
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		String description = "";
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					description = method.getAnnotation(UseUnitOfWork.class).description();
					break;
				}
			}
		}
		return description;
	}

}